package org.smile.josql;

import java.beans.IntrospectionException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.smile.beans.BeanUtils;
import org.smile.exception.JoSQLParseException;
import org.smile.josql.parse.JoSQLParser;
import org.smile.josql.parse.WhereTokener;
/**
 * JOSQL查询类
 * @author Administrator
 *
 */
public class Query {
	private static final Logger logger=Logger.getLogger(Query.class);
	
	private static final DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
	/**
	 * 是否反回所有字段
	 */
	private boolean isReturnAll=false;
	/**
	 * 查询语句
	 */
	private String josql;
	/**
	 * 返回的结果类型
	 */
	private String from;
	/**
	 * 返回每条记录的字段，如果是返回所有的字段，则这个属性可以不指定
	 */
	private List<String> result;
	private List orderby;
	private List group;
	private List<String> parameters=new ArrayList<String>();
	private JoSQLParser parser=new JoSQLParser();
	/**
	 * 条件过滤子句
	 */
	private String where;
	/**
	 * 
	 * @param josql
	 * @throws JoSQLParseException 
	 */
	public Query(String josql) throws JoSQLParseException{
		this.josql=josql;
		parser.parse(this);
	}
	/**
	 * 空构造方法
	 */
	public Query(){}
	/**
	 * 解析一条语句
	 * @param josql
	 * @throws JoSQLParseException 
	 */
	public void parse(String josql) throws JoSQLParseException{
		this.josql=josql;
		parser.parse(this);
	}
	/**
	 * 设置占位参数的值
	 */
	public void setParamter(String name,Object value){
		if(this.where==null) return;
		
		if(value instanceof String){
			this.where=this.where.replaceAll(":"+name, "'"+value+"'");
		}else if(value instanceof Date){
			this.where=this.where.replaceAll(":"+name, df.format(value));
		}else{
			this.where=this.where.replaceAll(":"+name,value+"");
		}
		this.parameters.add(name);
	}
	
	@SuppressWarnings("unchecked")
	public boolean filter(Map value) throws JoSQLParseException{
		if(this.where==null){
			return true;
		}
		String tempWhere=this.where;
		Map map=(Map)value;
		for(int i=0;i<this.parameters.size();i++){
			String temp=(String)this.parameters.get(i);
			Object v=map.get(temp);
			if(v instanceof Date){
				tempWhere=tempWhere.replaceAll(temp,"'"+df.format(v)+"'");
			}else{
				Object o=map.get(temp);
				if(o instanceof String){
					tempWhere=tempWhere.replaceAll(temp,"'"+o+"'");
				}else{
					tempWhere=tempWhere.replaceAll(temp,o+"");
				}
			}
		}
		logger.debug("where string:"+tempWhere);
		return parser.parseWhere(new WhereTokener(tempWhere));
	}
	/**
	 * 查询结果
	 * @param srcList
	 * @return
	 * @throws Exception 
	 * @throws IntrospectionException 
	 */
	@SuppressWarnings("unchecked")
	public List listResult(Collection srcList) throws IntrospectionException, Exception{
		List list=new ArrayList();
		Iterator iter=srcList.iterator();
		while(iter.hasNext()){
			Object value=iter.next();
			if(this.isReturnAll){
				if(!(value instanceof Map)){
					value=BeanUtils.mapFromBean(value);
				}
				if(this.filter((Map)value)){
					if("java.util.Map".equals(from)){
						list.add(value);
					}else{
						Object bean=Class.forName(from).newInstance();
						list.add(BeanUtils.mapToBean((Map)value, bean));
					}
				}
			}else{
				if(!(value instanceof Map)){
					value=BeanUtils.mapFromBean(value);
				}
				if(this.filter((Map)value)){
					Map map=new HashMap();
					for(int i=0;i<this.result.size();i++){
						String name=this.result.get(i);
						map.put(name, ((Map)value).get(name));
					}
					list.add(map);
				}
			}
		}
		return list;
	}
	/**
	 * 得到查询语句
	 * @return
	 */
	public String getJosql() {
		return josql;
	}
	public void setOrderby(List orderby) {
		this.orderby = orderby;
	}
	public void setGroup(List group) {
		this.group = group;
	}
	public void setFrom(String from) {
		this.from = from;
	}
	public void setResult(List result) {
		this.result = result;
	}
	public void setReturnAll(boolean isReturnAll) {
		this.isReturnAll = isReturnAll;
	}
	public void setWhere(String where) {
		this.where = where;
	}
	public String getWhere() {
		return where;
	}
	
}
